package com.qiangzi.workflow.engine.bpmn.base;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import javax.el.ExpressionFactory;
import javax.el.ValueExpression;
import javax.el.VariableMapper;

import org.springframework.util.Assert;

import com.qiangzi.workflow.engine.bpmn.expression.ConditionExpression;
import com.qiangzi.workflow.engine.listener.FlowEventListener;
import com.qiangzi.workflow.engine.listener.impl.FlowEventListenerImpl;

import de.odysseus.el.ExpressionFactoryImpl;
import de.odysseus.el.util.SimpleContext;
import lombok.Data;

@SuppressWarnings("unused")
public class ProcessInstance {

	private FlowEventListener listener = new FlowEventListenerImpl();

	// 所有候选节点在此
	private Map<String, Node> candidates;

	private String uuid;
	private String parent;

	// 当前实例的变量容器
	// private static Object OBJ = new Object();
	// private Map<String, Object> variables;
	private ExpressionFactory juelExpressionFactory;
	private SimpleContext juelContext;

	// 部署线程
	private Thread deployThread;

	public Thread getDeployThread() {
		return deployThread;
	}

	public FlowEventListener getListener() {
		return listener;
	}

	public void setDeployThread(Thread deployThread) {
		this.deployThread = deployThread;
	}

	public ProcessInstance() {

		uuid = UUID.randomUUID().toString();
		parent = null;
		candidates = new HashMap<String, Node>();

		// juel表达式相关
		// variables = new HashMap<String, Object>();
		juelExpressionFactory = new ExpressionFactoryImpl();
		juelContext = new SimpleContext();

	}

	public Map<String, Node> getCandidates() {
		return candidates;
	}

	public void addCandidate(Node candidate) {
		candidates.put(candidate.getId(), candidate);
	}

	public void removeCandidate(Node candidate) {
		candidates.remove(candidate.getId());
	}

	@SuppressWarnings("rawtypes")
	public ValueExpression setVariable(String varName, Object value, Class valueClass) throws Exception {
		Assert.hasText(varName, "var name must be valid");
		// 先判断是否已经有这个varName对应的,否则造成覆盖就不好
		// 经过讨论,可以覆盖老的变量
		// Assert.isTrue(null == variables.put(varName, OBJ), "dupliate var defined ->"
		// + varName);
		// 现在可以放心的放入到context里面去
		// 可覆盖老的变量,注意
		return juelContext.setVariable(varName, juelExpressionFactory.createValueExpression(value, valueClass));

	}

	public Object getVariable(String varName) {

		VariableMapper variableMapper = juelContext.getVariableMapper();
		// 判断是否为空
		if (null == variableMapper) {
			return null;
		}
		// 继续查找
		ValueExpression valueExpression = variableMapper.resolveVariable(varName);
		if (null == valueExpression) {
			return null;
		}
		// 继续查找
		return valueExpression.getValue(juelContext);

	}

	public boolean getExpressionValue(ConditionExpression conditionExpression) {
		Assert.isTrue(null != conditionExpression.getExpression(), "not valid expression");
		// 解析表达式
		ValueExpression e = juelExpressionFactory.createValueExpression(juelContext,
				conditionExpression.getExpression(), java.lang.Boolean.class);
		boolean result = (boolean) e.getValue(juelContext);
		return result;
	}

}
